package org.example.stream;

import org.junit.Test;

import javax.sound.midi.Soundbank;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @ClassName Demo1
 * @Description
 * @Author zhangsw
 * @Date 2020/11/20 9:08
 * @Version 1.0
 */
public class Demo1 {
    @Test
    public void test1() {
        //遍历Map
        System.out.println("遍历Map");
        Map<String, String> map = new HashMap<>();
        map.put("a", "a");
        map.put("b", "b");
        map.put("c", "c");
        map.put("d", "d");
        for (String key : map.keySet()) {
            System.err.println(key + "--" + map.get(key));
        }
        System.out.println("--------------------");
        map.forEach((k, v) -> {
            System.err.println(k + "--" + v);
        });
        //遍历List
        System.out.println("遍历List");
        List<String> list = new ArrayList<String>();
        list.add("a");
        list.add("bb");
        list.add("ccc");
        list.add("dddd");
//        for (String item : list) {
//            System.err.println(item);
//        }
        System.out.println("-------------------");
        list.forEach(System.err::println);
    }

    @Test
    public void test2() {
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("普通方式创建");
            }
        };
        r1.run();

        Runnable r2 = () -> System.out.println("拉达姆方式创建");
        r2.run();
    }

    @Test
    public void test3() {
        Stream<String> stream = Stream.of("a", "b", "c", "d");
        stream.forEach(System.out::println);
        String[] strArr = new String[]{"a", "b", "c"};
        stream = Stream.of(strArr);
        stream.forEach(System.err::println);
        stream = Arrays.stream(strArr);
        stream.forEach(System.out::println);
        List<String> list = Arrays.asList(strArr);
        stream = list.stream();
        stream.forEach(System.err::println);
    }

    /**
     * 一个Stream只能使用一次，重复使用会报stream has already been operated upon or closed异常
     */
    @Test
    public void test4() {
        Stream<String> stream = Stream.of("a", "b", "c");
        String[] strArr = stream.toArray(String[]::new);
        //转List
        List<String> list = stream.collect(Collectors.toList());
        //转List
        List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
        //转Set
        Set<String> set = stream.collect(Collectors.toSet());
        //转set
        HashSet<String> set2 = stream.collect(Collectors.toCollection(HashSet::new));
        //转Stack
        Stack<String> stack = stream.collect(Collectors.toCollection(Stack::new));
        stack.forEach(System.out::println);
    }

    @Test
    public void test5() {
        //Map用于映射每个元素到对应的结果
        List<String> list = Arrays.asList("Zs", "ls", "ww");
        /*转大写*/
        List<String> list2 = list.stream().map(String::toUpperCase).collect(Collectors.toList());
        System.out.println("转换后的：" + list2);

        List<String> intLIst = Arrays.asList("11", "10", "9");
        /*转类型*/
        List<Integer> intLIst2 = intLIst.stream().map(Integer::parseInt).collect(Collectors.toList());
        System.out.println("转换后：" + intLIst2);

        List<Integer> IntList22 = Arrays.asList(2, 3, 4);
        //开根
        List<Double> IntList222 = IntList22.stream().map(Math::sqrt).collect(Collectors.toList());
        //平方
        List<Integer> IntList2222 = IntList22.stream().map(n -> n * n).collect(Collectors.toList());
        System.out.println("转换后：" + IntList222);
        System.out.println("转换后：" + IntList2222);
    }

    @Test
    public void test6() {
        List<String> list = Arrays.asList("张三", "李四", "王五", "xuwujing");
        //findAny().orElse()找到返回查找到的结果，没找到返回没找到
        String res1 = list.stream().filter("李四"::equals).findAny().orElse("没找到");
        String res2 = list.stream().filter(str -> "李四2".equals(str)).findAny().orElse("没找到");
        System.err.println(res1);
        System.out.println(res2);

        List<User> lists = new ArrayList<User>();
        lists.add(new User(6, "张三"));
        lists.add(new User(2, "李四"));
        lists.add(new User(3, "王五"));
        lists.add(new User(1, "张三"));
        // 计算这个list中出现 "张三" id的值   使用mapToInt 求和
        int sum = lists.stream().filter(u -> "张三".equals(u.getName())).mapToInt(User::getAge).sum();
        System.out.println(sum);
    }

    /**
     * flatMap映射每个元素到对应结果 一对多
     */
    @Test
    public void test7() {
        String worlds = "The way of the future";
        List<String> list7 = new ArrayList<>();
        list7.add(worlds);
        List<String> list8 = list7.stream().flatMap(str -> Stream.of(str.split(" ")))
                .filter(world -> world.length() > 0).collect(Collectors.toList());
        System.err.println("单词");
        list8.forEach(System.out::println);
    }

    @Test
    public void test8() {
        Random rd = new Random();
        System.out.println("取前3条数据");
        rd.ints().limit(3).forEach(System.out::println);
//        rd.ints().forEach(System.out::println);
    }

    @Test
    public void test9() {
        List<User> list = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            User user = new User(i, "pancm" + i);
            list.add(user);
        }
        //截取之前的数据
        System.out.println(list.toString());
        // 取前3条数据，但是扔掉了前面的2条，可以理解为拿到的数据为 2<=i<3 (i 是数值下标)
        List<String> list2 = list.stream().map(User::getName).limit(3).skip(2).collect(Collectors.toList());
        System.out.println("截取之后的数据：" + list2);
    }

    @Test
    public void test10() {
        Random rd = new Random();
        //取前三条数据然后进行排序
        rd.ints().limit(3).sorted().forEach(System.out::println);

        List<User> list = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            User user = new User(i, "pancm" + i);
            list.add(user);
        }

        //普通排序
        List<User> list2 = list.stream().sorted((u1, u2) -> u1.getName().compareTo(u2.getName())).limit(3).collect(Collectors.toList());
        for (User user : list2) {
            System.out.println(user.toString());
        }
        System.out.println("---------------------------");
        //优化排序 先取值后排序
        List<User> list3 = list.stream().limit(3).sorted((u1, u2) -> u1.getName().compareTo(u2.getName())).collect(Collectors.toList());
        for (User user : list3) {
            System.out.println(user.toString());
        }
    }

    @Test
    public void test11() {
        //peek对每个元素执行操作并返回一个新的stream
        //双重操作
        Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> System.out.println("转换之前" + e))
                .map(String::toUpperCase).peek(e -> System.out.println("转换之后:" + e)).collect(Collectors.toList());
    }

    @Test
    public void test12() {
        //Stream parallel 使用
        //并行流
        List<String> strings = Arrays.asList("a", "", "c", "", "e", "", " ");
        //获取字符串的数量
        long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
        System.out.println("空字符串数量" + count);

        //最大值
        List<String> list13 = Arrays.asList("zhangsan", "lisi", "wangwu", "xuwujing");
        int max = list13.stream().mapToInt(String::length).max().getAsInt();
        //最小值
        int min = list13.stream().mapToInt(String::length).min().getAsInt();
        System.out.println("最长长度：" + max + "--最短长度：" + min);


        //得到去重后的数据
        String lines = "good good study day day up";
        List<String> list2 = new ArrayList<>();
        list2.add(lines);
        List<String> list3 = list2.stream().flatMap(line -> Stream.of(line.split(" "))).filter(w -> w.length() > 0)
                .map(String::toUpperCase).distinct().sorted().collect(Collectors.toList());
        //去重后
        System.out.println("去重后：" + list3);
    }

    /**
     * allMatch Stream中元素全部符合则返回true
     * anyMatch Stream中只要有一个元素符合就返回true
     * noneMatch Stream中没有一个元素符合就返回true
     */
    @Test
    public void test13() {
        Stream<Integer> stream1 = Stream.of(22, 11, 10, 2, 1);
        boolean b1 = stream1.allMatch(item -> item > 0);
        Stream<Integer> stream2 = Stream.of(22, 11, 10, 2, 1);
        boolean b2 = stream2.anyMatch(item -> item > 10);
        Stream<Integer> stream3 = Stream.of(22, 11, 10, 2, 1);
        boolean b3 = stream3.noneMatch(item -> item != 10);
        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b3);
    }

    /**
     * reduce
     * reduce 主要作用是把Stream元素组合起来进行操作
     */
    @Test
    public void test14() {
        //字符串拼接
        String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
        //得到最小值
        Double min = Stream.of(-4.0, 1.0, 3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
        //求和 无起始值
        Integer sum = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
        //求和 有起始值
        Integer sum2 = Stream.of(1, 2, 3, 4).reduce(1, Integer::sum);
        //过滤拼接
        String concat2 = Stream.of("a", "B", "c", "D", "e", "F").filter(x -> x.compareTo("Z") > 0)
                .reduce("", String::concat);
        System.out.println(concat);
        System.out.println(min);
        System.out.println(sum);
        System.out.println(sum2);
        System.out.println(concat2);
    }

    @Test
    public void test15() {
//        Stream.iterate(2, n -> n + 2).forEach(System.out::println);

        //生成一个等差数列
        //从2开始生成一个等差数列
        Stream.iterate(2, n -> n + 2).limit(5).forEach(x -> System.out.println(x + " "));

        //Supplier
        //通过实现Supplier类的方法可以自定义流计算规则。
        Stream.generate(new UserSupplier()).limit(2).forEach(u -> System.out.println(u.getAge() + ", " + u.getName()));

        System.out.println("通过age进行分组排序");
        Map<Integer, List<User>> mapLists = Stream.generate(new UserSupplier()).limit(5).collect(Collectors.groupingBy(User::getAge));
        Iterator<Map.Entry<Integer, List<User>>> it = mapLists.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Integer, List<User>> persons = (Map.Entry) it.next();
            System.out.println("age=" + persons.getKey() + "--" + "val=" + persons.getValue());
        }

        //分区排序
        Map<Boolean, List<User>> maps2 = Stream.generate(new UserSupplier()).limit(5).collect(Collectors.partitioningBy(u -> u.getAge() > 12));
        System.err.println(maps2.get(true));
        System.err.println(maps2.get(false));
    }

    @Test
    public void test16() {
        //IntSummaryStatistics用于收集统计信息，如count,min,max,sum,average的状态对象
        List<Integer> numbers = Arrays.asList(1, 5, 7, 3, 9);
        IntSummaryStatistics statistics = numbers.stream().mapToInt(x -> x).summaryStatistics();
        System.out.println("最大：" + statistics.getMax());
        System.out.println("最小：" + statistics.getMin());
        System.out.println("之和：" + statistics.getSum());
        System.out.println("平均数：" + statistics.getAverage());
    }
}

class UserSupplier implements Supplier<User> {
    private int index = 10;
    private Random random = new Random();

    @Override
    public User get() {
        return new User(index++, "pancm" + random.nextInt(10));
    }
}

class User {
    private Integer age;
    private String name;

    public User(Integer age, String name) {
        this.age = age;
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
